<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>06_Reflect-Reflect和Proxy共同完成代理</title>
  <!-- 
  在 JavaScript 中， `Reflect`  和  `Proxy`  是两个重要的内置对象，它们可以一起使用来实现对象的代理功能。
  1. 基本概念
  - Proxy：
    -  `Proxy`  是一个用于创建代理对象的构造函数，可以拦截和定义基本操作（如属性查找、赋值、枚举、函数调用等）。
    - 通过  `Proxy` ，可以在对目标对象进行操作时添加自定义行为。

  - Reflect：
    -  `Reflect`  是一个内置对象，提供了一组静态方法，用于操作对象的基本操作，主要是为了简化和改进对对象的操作。
    -  `Reflect`  方法通常与  `Proxy`  一起使用，以便在代理处理程序中执行默认行为。

  2. 使用 Proxy 和 Reflect 实现代理

  2.1 创建目标对象
  首先，定义一个目标对象，它是我们希望代理的对象。
  const target = {
      message: "Hello, world!",
      count: 0
  };
  2.2 创建代理
  使用  `Proxy`  创建一个代理对象，并定义拦截器（handler）来处理对目标对象的操作。
  const handler = {
      get(target, property, receiver) {
          console.log(`Getting property: ${property}`);
          return Reflect.get(target, property, receiver);
      },
      set(target, property, value, receiver) {
          console.log(`Setting property: ${property} to ${value}`);
          return Reflect.set(target, property, value, receiver);
      }
  };

  const proxy = new Proxy(target, handler);
  2.3 使用代理
  通过代理对象访问和修改目标对象的属性。
  console.log(proxy.message); // 输出: Getting property: message
                              // Hello, world!

  proxy.count = 1;            // 输出: Setting property: count to 1
  console.log(proxy.count);   // 输出: Getting property: count
                              // 1
  3. 代理的优势
  - 拦截操作：通过  `Proxy` ，可以在执行操作前或后添加自定义逻辑，例如记录日志、数据验证等。
  - 简化代码：使用  `Reflect`  使得在代理处理程序中调用目标对象的默认行为更加简单和一致，避免了重复的代码。

  4. 总结
  `Reflect`  和  `Proxy`  的结合使用为 JavaScript 提供了一种强大的方式来创建代理对象。 `Proxy`  允许开发者拦截和定义对象的基本操作，而  `Reflect`  提供了一组方法来简化对目标对象的操作。通过这种方式，开发者可以实现更灵活和强大的对象操作，增强代码的可维护性和可扩展性。
  -->
</head>
<body>

  <script>
    const obj = {
      name: '张三',
      age: 18
    }

    const proxy = new Proxy(obj, {
      get(target, key, receiver) {
        console.log('get', target, key, receiver)
        return Reflect.get(target, key)
      },
      set(target, key, newValue, receiver) {
        // 代理的好处
        // 1. 可以对数据进行校验
        // 2. 代理对象的目的: 不再之间操作原对象
        // 3. Reflect.set方法有返回值, 返回true/false, 可以判断是否设置成功
        console.log('set', target, key, newValue, receiver)
        const isSuccess = Reflect.set(target, key, newValue)
        if (isSuccess) {
          console.log('数据设置成功')
        } else {
          console.log('数据设置失败')
        }
        return isSuccess
      }
    })

    // 操作代理对象
    console.log(proxy.name)
    proxy.name = '李四'
    console.log(proxy.name)

  </script>
  
</body>
</html>